﻿using System.Collections.Generic;
using SLNGP.Core.Genes;
using SLNGP.Core.GeneticPrograms;

namespace SLNGP.Core.Individuals
{
    public interface IIndividual
    {
        /// <summary>
        /// Executes the phenotype Genetic Programming Tree and returns a single scalar value.
        /// </summary>
        /// <typeparam name="T">Type of Scalar return type.</typeparam>
        /// <param name="variables">Variables used when executing the Tree.</param>
        /// <returns>The Scalar value retrieved from the GP Tree.</returns>
        T ExecuteScalar<T>(params object[] variables);

        /// <summary>
        /// The current fitness of the individual. 
        /// </summary>
        object Fitness { get; set; }

        /// <summary>
        /// The first chromosome of the individual. 
        /// </summary>
        IChromosome Chromosome { get; set; }
        
        /// <summary>
        /// A marker used by the Selection Opearator to mark individuals for later genetic opearators to pick up on. 
        /// </summary>
        object SelectionMarker { get; set; }
        
        /// <summary>
        /// Gets a value indicating whether the current individual has a valid genotype. 
        /// </summary>
        bool IsValid { get; }
        
        /// <summary>
        /// If the current individual does not have a valid genotype, initiates a self fix. 
        /// </summary>
        void Fix();

        /// <summary>
        /// Gets or sets the Parent Genetic Program. 
        /// </summary>
        IGeneticProgram ParentGeneticProgram { get; set; }

        /// <summary>
        /// Get a list of all the genes.
        /// </summary>
        IEnumerable<IGene> AllGenes { get; }

        /// <summary>
        /// Clone current individual with a shallow/deep copy for a child creation.
        /// </summary>
        /// <returns>Cloned child.</returns>
        IIndividual CloneChild();

        /// <summary>
        /// Gets a language agnostic string display.
        /// </summary>
        string GetStringDisplay();
    }
}